<?php

defined("_ARKN_EXEC") or exit("no no, mr. superman no here");

require_once ROOT_FOLDER . "/php/configs/database_cfg.php";
require_once ROOT_FOLDER . "/php/scripts/role_scripts/Roles.php";

class Account {

	private $db;
	private $isDbConnected;
	private $logger;

	public function __construct() {
		$this->logger = Logger::getLogger("Account.php");
		$this->db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
		if($this->db->connect_error)
			throw new Exception("Database connection error");
	}

	public function addAccount($role, $firstname, $lastname, $username, $address, $email) {
		$this->logger->info("Account.addAccount enter.");
		$success = FALSE;
		$this->logger->info("Validating input data.");
		if(empty($role) && ($role < 1 || $role > 4))
			$this->logger->info("Role value is incorrect.");
		else if(empty($firstname))
			$this->logger->info("First name value is incorrect.");
		else if(empty($lastname))
			$this->logger->info("Last name value is incorrect.");
		else if(empty($username))
			$this->logger->info("Username name value is incorrect.");
		else if(empty($address))
			$this->logger->info("Address value is incorrect.");
		else if(empty($email))
			$this->logger->info("Email value is incorrect.");
		else {
			$this->logger->info("Input data is valid.");
			$password = $username . "123";
			$salt = $this->salt(128);
			$passHash = hash("sha512", $salt . $password);
			$this->logger->info("Preparing statement.");
			if($stmt = $this->db->prepare("insert into accounts(firstname, lastname, username, pword, roleid, address, email, salt)values(?, ?,?, ?, ?, ?, ?, ?)")) {
				$stmt->bind_param("ssssisss", $firstname, $lastname, $username, $passHash, $role, $address, $email, $salt);
				$stmt->execute();
				$stmt->store_result();
				$affectedRows = $stmt->affected_rows;
				$stmt->fetch();
				$stmt->close();
				if($affectedRows == 1) {
					$success = TRUE;
					$this->logger->error("Account with role " . Roles::name($role) . " has been inserted into the database.");
				} else
					$this->logger->error("Error occured while executing the SQL statement.");
			} else
				$this->logger->error("Error occured while preparing the SQL statement.");
		}
		$this->logger->info("Account.addAccount exit.");
		return $success;
	}

	public function studentList() {
		$this->logger->info("Account.studentList enter.");
		$index = 0;
		$returnList = NULL;
		if($stmt = $this->db->prepare("select accountid, firstname, lastname, username, address, email from accounts where roleid = ?")) {
			$roleid = Roles::Student;
			$stmt->bind_param("i", $roleid);
			$stmt->execute();
			$stmt->store_result();
			if(!$stmt->errno) {
				$results = $this->bind_result_array($stmt);
				$returnList = array();
				while($stmt->fetch())
					$returnList[$index++] = $this->getCopy($results);
				$stmt->close();
				$this->logger->info("Selected " . $index . " students.");
			} else
				$this->logger->info("Error occured while executing the SQL statement.");
		} else
			$this->logger->info("Error occured while preparing the SQL statement.");
		$this->logger->info("Account.studentList exit.");
		return $returnList;
	}

	public function studentBasicInfo($studentid) {
		$this->logger->info("Account.studentBasicInfo enter.");
		$studentBasicInfo = NULL;
		if($stmt = $this->db->prepare("select accountid, firstname, lastname, username, address, email from accounts where roleid = ? and accountid = ?")) {
			$roleid = Roles::Student;
			$studentBasicInfo = array();
			$stmt->bind_param("ii", $roleid, $studentid);
			$stmt->execute();
			$stmt->store_result();
			if(!$stmt->errno && $stmt->num_rows == 1) {
				$studentBasicInfo = $this->bind_result_array($stmt);
				$stmt->fetch();
				$stmt->close();
			} else
				$this->logger->info("Error occured while executing the SQL statement.");
		} else
			$this->logger->info("Error occured while preparing the SQL statement.");
		$this->logger->info("Account.studentBasicInfo exit.");
		return $studentBasicInfo;
	}
	
	public function studentPayments($studentid) {
		$this->logger->info("Account.studentPayments enter.");
		$payments = NULL;
		$count = 0;
		if($stmt = $this->db->prepare("select paydate, amount from payment_history where studentid = ?")) {			
			$stmt->bind_param("i", $studentid);
			$stmt->execute();
			$stmt->store_result();
			if(!$stmt->errno) {
				$results = $this->bind_result_array($stmt);
				$payments = array();
				while($stmt->fetch())
					$payments[$count++] = $this->getCopy($results);
				$stmt->close();
			} else
				$this->logger->info("Error occured while executing the SQL statement.");
		} else
			$this->logger->info("Error occured while preparing the SQL statement.");
		$this->logger->info("Account.studentPayments exit.");
		return $payments;
	}
	
	public function studentDepartments($studentid) {
		$this->logger->info("Account.studentDepartments enter.");
		$departments = NULL;
		$count = 0;
		if($stmt = $this->db->prepare("select d.departmentid as departmentid, d.name as name, s.city as city from departments d, sites s, studdep sd where d.siteid = s.siteid and sd.departmentid = d.departmentid and sd.studentid = ?")) {
			$stmt->bind_param("i", $studentid);
			$stmt->execute();
			$stmt->store_result();
			if(!$stmt->errno) {
				$results = $this->bind_result_array($stmt);
				$departments = array();
				while($stmt->fetch())
					$departments[$count++] = $this->getCopy($results);
				$stmt->close();
			} else
				$this->logger->info("Error occured while executing the SQL statement.");
		} else
			$this->logger->info("Error occured while preparing the SQL statement.");
		$this->logger->info("Account.studentDepartments exit.");
		return $departments;
	}
	
	public function studentCourses($studentid, $departmentid) {
		$this->logger->info("Account.studentCourses enter.");
		$courses = NULL;
		$count = 0;
		if($stmt = $this->db->prepare("select c.name as name, a.firstname as firstname, a.lastname as lastname, co.examdate as examdate, g.grade as grade, c.credits as credits " .
									  "from grades g, course_offerings co, courses c, accounts a " .
									  "where g.offeringid = co.offeringid " .
									  "and a.accountid = co.teacherid " .
									  "and c.courseid = co.courseid " .
									  "and g.studentid = ? " .
									  "and c.departmentid = ?")) {
			$stmt->bind_param("ii", $studentid, $departmentid);
			$stmt->execute();
			$stmt->store_result();
			if(!$stmt->errno) {
				$results = $this->bind_result_array($stmt);
				$courses = array();
				while($stmt->fetch())
					$courses[$count++] = $this->getCopy($results);
				$stmt->close();
			} else
				$this->logger->info("Error occured while executing the SQL statement.");
		} else
			$this->logger->info("Error occured while preparing the SQL statement.");
		$this->logger->info("Account.studentCourses exit.");
		return $courses;
	}
	
	function bind_result_array($stmt) {
		$meta = $stmt->result_metadata();
		$results = array();
		while ($field = $meta->fetch_field()) {
			$results[$field->name] = NULL;
			$params[] = &$results[$field->name];
		}
		call_user_func_array(array($stmt, "bind_result"), $params);
		return $results;
	}

	function getCopy($row) {
		return array_map(create_function('$a', 'return $a;'), $row);		
	}

	public function findStudent(&$firstname, &$lastname, &$address, &$email) {
		$this->logger->info("Find student from DB.enter.");
		if($stmt = $this->db->prepare("select firstname, lastname, address, email  from accounts where email=?")) {
			$stmt->bind_param("s", $email);
			$stmt->execute();
			$stmt->store_result();
			if($stmt->num_rows == 1) {
				$this->logger->info("Select student info.enter");
				$stmt->bind_result($firstname, $lastname, $address, $email);
				$stmt->fetch();
				$stmt->close();
				$this->logger->info("Student selected.");
				$this->logger->info("Select student info.exit");
				return True;
			} else {
				$this->logger->info("Student does not exist.");
				$this->logger->info("Select student info.exit");
				return False;
			}
			return True;
		}
		$this->logger->info("Find student from DB.exit.");
		return False;
	}

	public function editAccount($currentemail, $newaddress, $newemail) {
		$this->logger->info("Edit a student in DB.enter.");
		if($stmt = $this->db->prepare("update accounts SET email=?,address=? where email=?")) {
			$stmt->bind_param("sss", $newemail, $newaddress, $currentemail);
			$stmt->execute();
			$stmt->store_result();
			$this->logger->info("Edit a student in DB.exit.");
			return True;
		} else {
			$this->logger->info("Edit a student in DB.exit.");
			return False;
		}

		return False;
	}

	function salt($length) {
		$chars = "a0b9c8d7e6f5g4h3i2j1k~l'm;n[n}o]p{q/r\\s*t-u+v=w;xyz";
		$size = strlen($chars);
		$saltTemp = "";
		for($i = 0; $i < $length; $i++) {
			$saltTemp .= $chars[rand(0, $size - 1)];
		}
		return $saltTemp;
	}

	public function __destruct() {
		if($this->db != NULL) {
			$this->db->kill($this->db->thread_id);
			$this->db->close();
		}
	}

}

$account = new Account();
?>
